/*
 * AreaDesenho2.java
 *
 * Created on 4 de Abril de 2007, 19:50
 */
package moduledefault.classify.c45.rafael.view.jpanel.graph;

import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 *
 * @author  cccasagrande
 */
public class AreaDesenho extends JPanel implements MouseMotionListener, MouseListener, MouseWheelListener {

    public static final int OPERACAO_NOT = -1;
    public static final int OPERACAO_DESENHAR_ESTADO = 0;
    public static final int OPERACAO_DESENHAR_TRANSICAO = 1;
    public static final int OPERACAO_SELECIONAR = 2;
    //
    private MapaGrafico grafo;
    private ObjetoGrafico objetoTemp;
    private int tipoOperacao;
    private Aresta tempTrans;
    private double raio;
    private JScrollPane scroll;
    MouseEvent event;
    private boolean editavel;
    private ImageIcon imageBackground;
    private boolean movendoTrans;
    private double zoom = 1;
    private Dimension d;

    public int getFolha() {
        return folha;
    }

    public void setFolha(int folha) {
        this.folha = folha;
    }

    public int getMaiorNivel() {
        return maiorNivel;
    }

    public void setMaiorNivel(int maiorNivel) {
        this.maiorNivel = maiorNivel;
    }
    int folha;
    int maiorNivel;

    public void setZoom(double zoom) {
        this.zoom = zoom;
        scroll.setPreferredSize(this.getPreferredSize());
        scroll.setSize(this.getSize());
        scroll.revalidate();
    }

    public double getZoom() {
        return this.zoom;
    }

    /** Creates new form AreaDesenho2 */
    public AreaDesenho(JScrollPane scr) {
        initComponents();

        scroll = scr;
        tempTrans = null;
        grafo = new MapaGrafico();
        event = null;
        tipoOperacao = OPERACAO_NOT;
        raio = 20;
        objetoTemp = null;
        editavel = false;
        addMouseMotionListener(this);
        addMouseListener(this);
        movendoTrans = false;
        imageBackground = null;
    }

    public void zoomIn() {
        zoom *= 2;
//        paintComponent(this.getGraphics());
        redimensiona();
    }

    public void zoomOut() {
        zoom /= 2;
        redimensiona();
//        paintComponent(this.getGraphics());
    }

    public void redimensiona() {
//        d = this.getPreferredSize();
//        Dimension d2 = new Dimension();
//        d2.height = (int) (d.height * zoom);
//        d2.width = (int) (d.width * zoom);
//        Component c = this.getParent();
//        Dimension dc = c.getPreferredSize();
//        if (dc.height > d2.height) {
//            d2.height = dc.height;
//        }
//        if (dc.width > d2.width) {
//            d2.width = dc.width;
//        }
//        this.setPreferredSize(d2);
//        this.setSize(d2);
////        System.out.println(d2.toString() + " " + d.toString());
//        scroll.revalidate();
////        scroll.setSize(d2);
////        scroll.setPreferredSize(d2);
////        scroll.revalidate();


        Dimension d = scroll.getPreferredSize();
//        d = this.getPreferredSize();
        Dimension d2 = new Dimension();
        d2.height = (int) (d.height * zoom);
        d2.width = (int) (d.width * zoom);

        Component c = this.getParent();
        Dimension dc = c.getPreferredSize();
        dc.height = d2.height;
        dc.width = d2.width;
        
        if (dc.height < d.height) {
            dc.height = d.height;
        }
        if (dc.width < d.width) {
            dc.width = d.width;
        }
        this.setPreferredSize(d2);
        this.setSize(d2);
        c.setPreferredSize(dc);
        c.setSize(dc);
//        System.out.println(d2.toString() + " " + d.toString());
        scroll.revalidate();
        this.updateUI();
//        scroll.setSize(d2);
//        scroll.setPreferredSize(d2);
//        scroll.revalidate();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPopupMenuEstado = new javax.swing.JPopupMenu();
        jMenuItemAlterarID = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JSeparator();
        jMenuItemRemover = new javax.swing.JMenuItem();
        jPopupMenuTrans = new javax.swing.JPopupMenu();
        jMenuItemRemoverT = new javax.swing.JMenuItem();

        jMenuItemAlterarID.setFont(new java.awt.Font("Courier New", 0, 11));
        jMenuItemAlterarID.setText("Alterar Rótulo");
        jMenuItemAlterarID.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemAlterarIDActionPerformed(evt);
            }
        });
        jPopupMenuEstado.add(jMenuItemAlterarID);
        jPopupMenuEstado.add(jSeparator2);

        jMenuItemRemover.setFont(new java.awt.Font("Courier New", 0, 11));
        jMenuItemRemover.setText("Remover");
        jMenuItemRemover.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemRemoverActionPerformed(evt);
            }
        });
        jPopupMenuEstado.add(jMenuItemRemover);

        jMenuItemRemoverT.setFont(new java.awt.Font("Courier New", 0, 11));
        jMenuItemRemoverT.setText("Remover");
        jMenuItemRemoverT.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemRemoverTActionPerformed(evt);
            }
        });
        jPopupMenuTrans.add(jMenuItemRemoverT);

        setForeground(new java.awt.Color(153, 153, 0));
        setFont(new java.awt.Font("Times New Roman", 0, 11)); // NOI18N
        setMinimumSize(new java.awt.Dimension(772, 547));
        setPreferredSize(new java.awt.Dimension(772, 547));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 772, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 547, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents
//
    private void jMenuItemRemoverTActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemRemoverTActionPerformed
        Aresta trans = (Aresta) objetoTemp;
        grafo.removerObjeto(trans);
    }//GEN-LAST:event_jMenuItemRemoverTActionPerformed

    /** estado inicial*/
    /**alterar id*/
    private void jMenuItemAlterarIDActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemAlterarIDActionPerformed
        Vertice aux = (Vertice) objetoTemp;
        aux.getIdentificador();
        String rot = new String();
        rot = JOptionPane.showInputDialog(this, "Qual o Novo Rótulo?", "Mensagem", 0);

        int vet[] = grafo.getVertices();
        boolean existe = false;
        for (int i = 0; i < vet.length; i++) {
            Vertice v = grafo.getVertice(vet[i]);
            if (v.getRotulo().compareTo(rot) == 0 && aux.getIdentificador() != v.getIdentificador()) {
                existe = true;
            }
        }

        if (!existe) {
            aux.setRotulo(rot);
        } else {
            JOptionPane.showMessageDialog(this, "Rótulo já existente!!!", "Mensagem: Erro", 0);
        }
        repaint();
    }//GEN-LAST:event_jMenuItemAlterarIDActionPerformed

    /**remover estado*/
    private void jMenuItemRemoverActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemRemoverActionPerformed
        grafo.removerObjeto(objetoTemp);
    }//GEN-LAST:event_jMenuItemRemoverActionPerformed

    public void mouseDragged(MouseEvent e) {
        event = e;
        Rectangle r = new Rectangle(e.getX() - 100, e.getY() - 100, 200, 200);
        this.scrollRectToVisible(r);
        if (editavel) {
            if (tipoOperacao == OPERACAO_SELECIONAR) {
                if (objetoTemp instanceof Vertice) {
                    Vertice aux = (Vertice) objetoTemp;
                    int id = aux.getIdentificador();
                    grafo.moveVertice(id, e.getPoint());

                } else {
                    if (objetoTemp instanceof Aresta) {
                        Aresta aux = (Aresta) objetoTemp;
                        if (movendoTrans) {
                            aux.setPControle(e.getPoint());
                        }
                    }
                }
            }
        }
        repaint();
    }

    public void mouseMoved(MouseEvent e) {
        event = e;
        Rectangle r = new Rectangle(e.getX() - 100, e.getY() - 100, 200, 200);
        //this.scrollRectToVisible(r);

        if (editavel) {
            if (tipoOperacao == OPERACAO_DESENHAR_ESTADO) {
            }
            if (tipoOperacao == OPERACAO_DESENHAR_TRANSICAO) {
                if (tempTrans != null) {
                    tempTrans.setPTemp(e.getPoint());
                }
            }
            if (tipoOperacao == OPERACAO_SELECIONAR) {
                if (grafo.isSobreObjeto(e.getPoint())) {
                    setCursor(new Cursor(12));
                } else {
                    setCursor(new Cursor(0));
                }
            }
        }
        repaint();
    }

    public void mouseClicked(MouseEvent e) {
        if (editavel) {
            if (tipoOperacao == OPERACAO_DESENHAR_ESTADO) {
                inserirVertice(e.getPoint(), Vertice.TIPO_COR_0);
                atualizarDimensaoJanela();
            }
            if (tipoOperacao == OPERACAO_DESENHAR_TRANSICAO && !e.isMetaDown()) {
                ObjetoGrafico obj = grafo.getObjetoSelecionado(e.getPoint());
                if (obj instanceof Vertice) {
                    Vertice aux = (Vertice) obj;
                    if (tempTrans == null) {//sua constru��o n�o foi iniciada

                        tempTrans = new Aresta(grafo.getPropriedades(), "");
                        tempTrans.setIdOrigem(aux.getIdentificador());
                        tempTrans.setPOrigem(aux.getPo());

                        tempTrans.setPTemp(new Point((int) (aux.getPo().getX() + 10), (int) (aux.getPo().getY() + 10)));
                    } else {
                        tempTrans.setIdDestino(aux.getIdentificador());
                        tempTrans.setPDestino(aux.getPo());

                        if (!grafo.isAresta(tempTrans.getIdOrigem(), tempTrans.getIdDestino())) {
                            if (tempTrans.getIdDestino() == tempTrans.getIdOrigem()) {
                                tempTrans = null;
                            } else {
                                grafo.inserirAresta(tempTrans);
                                atualizarDimensaoJanela();
                            }
                        }
                        tempTrans = null;
                    }
                } else {
                    tempTrans = null;
                }
            }
            if (tipoOperacao == OPERACAO_SELECIONAR) {
            }
        }
        repaint();
    }

    public void mousePressed(MouseEvent e) {
        if (editavel) {
            if (tipoOperacao == OPERACAO_DESENHAR_ESTADO) {
                mouseClicked(e);
            }
            if (tipoOperacao == OPERACAO_DESENHAR_TRANSICAO) {

            }
            if (tipoOperacao == OPERACAO_SELECIONAR) {

                if (e.isMetaDown()) {
                    if (grafo.isSobreObjeto(e.getPoint())) {

                        if (objetoTemp instanceof Aresta) {
                            Aresta aux2 = (Aresta) objetoTemp;
                            aux2.desfazerSelecao();
                        }
                        objetoTemp = grafo.getObjetoSelecionado(e.getPoint());

                        if (objetoTemp instanceof Vertice) {
                            Vertice aux = (Vertice) objetoTemp;
                            jPopupMenuEstado.show(this, e.getX(), e.getY());
                        } else {
                            if (objetoTemp instanceof Aresta) {
                                jPopupMenuTrans.show(this, e.getX(), e.getY());
                            }
                        }
                        setCursor(new Cursor(12));
                    } else {
                        setCursor(new Cursor(0));
                        objetoTemp = null;
                    }
                } else {
                    if (objetoTemp instanceof Aresta) {
                        Aresta aux2 = (Aresta) objetoTemp;

                        if (aux2.isSobreControle(e.getPoint())) {
                            movendoTrans = true;
                        } else {
                            aux2.desfazerSelecao();
                            objetoTemp = null;
                        }
                    } else {
                        ObjetoGrafico aux = grafo.getObjetoSelecionado(e.getPoint());
                        if (aux instanceof Vertice) {
                            objetoTemp = aux;
                        }
                        if (aux instanceof Aresta) {
                            Aresta trans = (Aresta) aux;
                            trans.selecionarCurva();
                            objetoTemp = trans;
                        }
                    }
                }
            }
        }
        repaint();
    }

    public void mouseReleased(MouseEvent e) {
        if (editavel) {
            if (tipoOperacao == OPERACAO_SELECIONAR) {
                movendoTrans = false;
                atualizarDimensaoJanela();
            }
        }
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2D = (Graphics2D) g;
        g2D.scale(zoom, zoom);
        super.paintComponent(g);

        if (imageBackground != null) {
            Image imagem = imageBackground.getImage();
            g.drawImage(imagem, 0, 0, this);
        }
        if (editavel) {
            grafo.paint(g2D);
            if (tempTrans != null) {
                tempTrans.plota(g2D);
            }
        }
    }

    public Vertice inserirVertice(Point p, int tipoCor) {
        /*if (grafo.isSobrepoeVertice(p, raio)) {
        return null;
        }*/
        int id = grafo.getProximoEstadoMenorDesocupado();

        Vertice est = new Vertice(id, p, tipoCor, grafo.getPropriedades());
        est.setRotulo(id + "");

        grafo.inserirVertice(est);
        return est;
    }

    public void setTipoOperacao(int op) {
        tempTrans = null;
        tipoOperacao = op;
        setCursor(new Cursor(0));
    }

    public void atualizarDimensaoJanela() {
        Rectangle rect = grafo.getRetanguloEnvolveObjetos();
        if (rect != null) {

            Dimension ds = this.getSize();

            int w, h;
            if (ds.getWidth() < (rect.getWidth() + rect.getX())) {
                w = (int) (rect.getWidth() + rect.getX() + 50);
            } else {
                w = (int) ds.getWidth();
            }

            if (ds.getHeight() < (rect.getHeight() + rect.getY())) {
                h = (int) (rect.getHeight() + rect.getY() + 50);
            } else {
                h = (int) ds.getHeight();
            }

            int x = (int) rect.getX();
            int y = (int) rect.getY();
            if (x < 0) {
                x = (x * (-1)) + 50;
            } else {
                x = 0;
            }
            if (y < 0) {
                y = (y * (-1)) + 50;
            } else {
                y = 0;
            }
            if (imageBackground != null) {
                if (w < imageBackground.getIconWidth()) {
                    w = imageBackground.getIconWidth();
                }
                if (h < imageBackground.getIconHeight()) {
                    h = imageBackground.getIconHeight();
                }

            }

            grafo.translacao(x, y);
            if (x == 0 && y == 0) {
                setPreferredSize(new Dimension(w, h));
                revalidate();
            } else {
                if (x == 0 && y != 0) {
                    setPreferredSize(new Dimension(w, h + 100));
                    revalidate();
                } else {
                    if (x != 0 && y == 0) {
                        setPreferredSize(new Dimension(w + 100, h));
                        revalidate();
                    } else {
                        setPreferredSize(new Dimension(w + 100, h + 100));
                        revalidate();
                    }
                }
            }

        } else {
            if (imageBackground != null) {
                setPreferredSize(new Dimension(imageBackground.getIconWidth(), imageBackground.getIconHeight()));
                revalidate();
            }
        }
        scroll.repaint();
        System.out.println("deve aumentar!!!");
    }

    public void deslocarGraficoOrigem() {
        Rectangle ret = grafo.getRetanguloEnvolveObjetos();

        int h, w;

        if (ret.getWidth() < 1024) {
            w = 1024;
        } else {
            w = (int) ret.getWidth() + 80;
        }

        if (ret.getHeight() < 768) {
            h = 768;
        } else {
            h = (int) ret.getHeight() + 80;
        }

        Dimension auxD = new Dimension(w, h);
        this.setPreferredSize(auxD);
        this.revalidate();
        if (ret != null) {
            int dx = (int) ret.getX() - 40;
            int dy = (int) ret.getY() - 40;
            grafo.translacao(-dx, -dy);
        }
        //atualizarDimensaoJanela();
        repaint();
    }

    public MapaGrafico getGrafoGrafico() {
        return grafo;
    }

    public void novoGrafo() {
        grafo = new MapaGrafico();
        objetoTemp = null;
        tempTrans = null;
    }

    public void abrir(MapaGrafico aut) {
        tempTrans = null;
        grafo = aut;
        if (grafo == null) {
            editavel = false;
        }
    }

    public void setEditavel(boolean bool) {
        editavel = bool;
    }

    private boolean isElemento(Vector vet, int d) {
        for (int i = 0; i < vet.size(); i++) {
            int v = Integer.parseInt((String) vet.get(i));
            if (v == d) {
                return true;
            }
        }
        return false;
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem jMenuItemAlterarID;
    private javax.swing.JMenuItem jMenuItemRemover;
    private javax.swing.JMenuItem jMenuItemRemoverT;
    private javax.swing.JPopupMenu jPopupMenuEstado;
    private javax.swing.JPopupMenu jPopupMenuTrans;
    private javax.swing.JSeparator jSeparator2;
    // End of variables declaration//GEN-END:variables
    public void setImageBackgraound(ImageIcon image) {
        imageBackground = image;
        atualizarDimensaoJanela();
        repaint();
    }

    public Propriedades getPropriedades() {
        return grafo.getPropriedades();
    }

    public void setPropriedades(Propriedades p) {
        grafo.setPropriedades(p);
    }

    public void atualizarPropriedades() {
        grafo.atualizarPropriedades();
        repaint();
    }

    public void mouseWheelMoved(MouseWheelEvent e) {
        System.out.println(e.getWheelRotation());
    }
}
